package com.qf.shop.car.controller;

import com.qf.shop.car.feign.GoodsService;
import com.qf.shop.car.interceptor.UserCarInterceptor;
import com.qf.shop.common.vo.CarVo;
import com.qf.shop.common.vo.StoreCarVo;
import com.qf.shop.common.vo.UserCarVo;
import com.qf.shop.common.constants.CarConstants;
import com.qf.shop.common.exception.BusinessException;
import com.qf.shop.common.utils.R;
import com.qf.shop.common.vo.GoodsVo;
import com.qf.shop.common.vo.StoreVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.math.BigDecimal;
import java.util.*;

@Controller
@RequestMapping("/car")
@Slf4j
public class CarController {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private UserCarInterceptor userCarInterceptor;

    @Autowired
    private GoodsService goodsService;

    @PostMapping("/add")
    @ResponseBody
    public R add(@RequestBody CarVo carVo, HttpSession session) {
        log.debug("car:{}", carVo);
        // 获取当前用户的的id
        String userCarId = userCarInterceptor.get();
        // hash绑定
        BoundHashOperations<String, Object, Object> carHashMap = stringRedisTemplate.boundHashOps(CarConstants.CAR_PRE + userCarId);

        // 此时的field是:商铺ID_商品ID
        String field = carVo.getSid() + "_" + carVo.getGid();

        carHashMap.increment(field, Long.parseLong(carVo.getCount().toString()));

        return R.ok();
    }

    @GetMapping("/getUserCarCount")
    @ResponseBody
    public Integer getUserCarCount(HttpServletRequest request) {
        return getUserCarVo(null).getSize();
    }

    @GetMapping("/getUserCarList")
    public String getUserCarList(ModelMap modelMap) {
        modelMap.put("userCarVo", getUserCarVo(null));
        return "carList"; // 返回的视图名称
    }


    public UserCarVo getUserCarVo(Set<Object> keyList) {

        // 最终返回给前端的购物车对象
        UserCarVo userCarVo = new UserCarVo();

        List<CarVo> carVoList = new ArrayList<>();
        Set<Object> keys = null;

        // 1.获取用户购物车的id
        String userCarId = userCarInterceptor.get();

        // 2.绑定
        BoundHashOperations<String, Object, Object> hashOperations = stringRedisTemplate.boundHashOps(CarConstants.CAR_PRE + userCarId);

        if (keyList == null || keyList.isEmpty()) {
            // 3.获取所有商品id
            keys = hashOperations.keys();
        } else {
            keys = keyList;
        }

        // 定义总价
        BigDecimal totalPrice = new BigDecimal(0.0);

        for (Object key : keys) {

            // 获取商品ID
            String gIdStr = key.toString().split("_")[1];

            int gid = Integer.parseInt(gIdStr.toString());
            int count = Integer.parseInt(hashOperations.get(key).toString());

            CarVo carVo = new CarVo();
            carVo.setGid(gid);
            carVo.setCount(count);
            // 根据商品Id查询商品对象
            GoodsVo goodsVo = goodsService.getGoodsVoById(gid);
            carVo.setGoodsVo(goodsVo);

            // 价格*数量
            BigDecimal subTotal = goodsVo.getGprice().multiply(BigDecimal.valueOf(count));
            carVo.setSubTotal(subTotal);

            carVoList.add(carVo);

            // 总价=所有的小计累加
            totalPrice = totalPrice.add(subTotal);
        }

        // 创建一个商品的集合
        List<StoreCarVo> storeCarVoList = new ArrayList<>();

        // 准备一个set用来去重
        Set<StoreVo> storeVoSet = new HashSet<>();
        // 把所有的商品中的商铺取出来
        for (CarVo carVo : carVoList) {
            storeVoSet.add(carVo.getGoodsVo().getStoreVo());
        }

        // 把去重后的商铺放到storeCarVoSet
        for (StoreVo storeVo : storeVoSet) {
            StoreCarVo storeCarVo = new StoreCarVo();
            storeCarVo.setStoreVo(storeVo);
            for (CarVo carVo : carVoList) {
                Integer carSid = carVo.getGoodsVo().getStoreVo().getId();
                if (storeVo.getId() == carSid) {
                    List<CarVo> carVoList1 = storeCarVo.getCarVoList();
                    if (carVoList1 == null) {
                        carVoList1 = new ArrayList<>();
                        carVoList1.add(carVo);
                        storeCarVo.setCarVoList(carVoList1);
                    } else {
                        carVoList1.add(carVo);
                    }
                }
            }
            storeCarVoList.add(storeCarVo);
        }

        // 根据商铺的信息找购物车去
        userCarVo.setStoreCarVoList(storeCarVoList);
        userCarVo.setSize(carVoList.size());
        userCarVo.setTotalPrice(totalPrice);
        log.debug("userCarVo --> :{}", userCarVo);
        return userCarVo;
    }

    @PostMapping("/carSelectGoods")
    @ResponseBody
    public R carSelectGoods(@RequestBody List<String> sGid) {
        log.debug("selectGid:{}", sGid);

        String userCarId = userCarInterceptor.get();

        BoundHashOperations<String, Object, Object> carMap = stringRedisTemplate.boundHashOps(CarConstants.CAR_PRE + userCarId);

        // 总价
        BigDecimal totalPrice = new BigDecimal(0.0);

        for (String key : sGid) {
            String[] s = key.split("_");

            Integer sid = Integer.parseInt(s[0]);

            Integer gid = Integer.parseInt(s[1]);

            GoodsVo goodsVo = goodsService.getGoodsVoById(gid);
            BigDecimal gprice = goodsVo.getGprice(); // 商品价格

            // 获取商品的数量
            Integer count = Integer.parseInt(carMap.get(key).toString());

            // 计算小计
            totalPrice = totalPrice.add(gprice.multiply(BigDecimal.valueOf(count)));
        }
        return R.ok().put("totalPrice", totalPrice);
    }


    @PostMapping("/updateCarCount")
    @ResponseBody
    public R updateCarCount(@RequestBody CarVo carVo) {
        log.debug("car:{}", carVo);

        String userCarId = userCarInterceptor.get();
        BoundHashOperations<String, Object, Object> carMap = stringRedisTemplate.boundHashOps(CarConstants.CAR_PRE + userCarId);
        String key = carVo.getSid().toString() + "_" + carVo.getGid();

        // 先查询购物车中商品的数量
        Integer count = Integer.parseInt(carMap.get(key).toString());

        // 判断自增还是自减
        switch (carVo.getStatus()) {
            case "add":

                // 判断库存是充足
                GoodsVo goodsVo = goodsService.getGoodsVoById(carVo.getGid());
                Integer stock = goodsVo.getStock();
                if (stock <= count) {
                    throw new BusinessException("库存不足", 4001);
                }

                carMap.increment(key, 1); // 自增
                break;
            case "sub":

                if (count <= 1) {
                    throw new BusinessException("购买的数量不能小于0", 4001);
                }

                carMap.increment(key, -1);
                break;
        }
        return R.ok();

    }


    @GetMapping("/delCar/{sid}/{gid}")
    @ResponseBody
    public R delCar(@PathVariable String sid, @PathVariable String gid) {
        String userCarId = userCarInterceptor.get();
        String key = sid + "_" + gid;
        stringRedisTemplate.opsForHash().delete(CarConstants.CAR_PRE + userCarId, key);
        return R.ok();
    }

    // 这个方法有feign来调用，会出现请求头丢失的问题，需要写拦截器来解决
    // 登录成功后合并购物车
    @GetMapping("/mergeCar")
    @ResponseBody
    public R mergeCar(String uid) {
        log.debug("合并购车,uid:{}", uid);

        // 获取当前的request对象
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();

        // 获取匿名用户购物车的key
        Cookie[] cookies = request.getCookies();
        if (cookies != null && cookies.length > 0) {
            String val = null;
            for (Cookie cookie : cookies) {
                String name = cookie.getName();
                if (CarConstants.CAR_ANON_NAME.equals(name)) {
                    val = cookie.getValue();
                    break;
                }
            }

            if (!StringUtils.isEmpty(val)) {

                // 绑定未登录的购物车
                BoundHashOperations<String, Object, Object> annonCarMap = stringRedisTemplate.boundHashOps(CarConstants.CAR_PRE + val);
                if (annonCarMap != null && annonCarMap.size() > 0) {
                    // 绑定登录后的购物车
                    log.debug("登录用户的购物车的id:{}", uid);
                    BoundHashOperations<String, Object, Object> loginCarMap = stringRedisTemplate.boundHashOps(CarConstants.CAR_PRE + uid);

                    Map<Object, Object> entries = annonCarMap.entries();
                    for (Map.Entry<Object, Object> entry : entries.entrySet()) {
                        String key = entry.getKey().toString(); // 2_12
                        Long value = Long.parseLong(entry.getValue().toString()); // 10
                        loginCarMap.increment(key, value);
                    }

                    // 清空购物车
                    stringRedisTemplate.delete(CarConstants.CAR_ANON_NAME + val);

                }
            }
        }
        return R.ok();
    }

    // 返回用户指定的购车的信息
    @PostMapping("/getUserCar")
    @ResponseBody
    public UserCarVo getUserCar(String key) {
        String[] split = key.split(",");
        Set<Object> set = new HashSet<>();
        for (String s : split) {
            set.add(s);
        }
        log.debug("keyList:{}", key);
        return getUserCarVo(set);
    }

    @GetMapping("/clearUserCar")
    @ResponseBody
    void clearUserCar(@RequestParam("uid") String uid, @RequestParam("selectGid") String selectGid){
        BoundHashOperations<String, Object, Object> hashOperations = stringRedisTemplate.boundHashOps(CarConstants.CAR_PRE + uid);
        hashOperations.delete(selectGid.split(","));
    }
}
